<template>
	<view class="win">
		<view class="btn-area">
			<view class="title">本机蓝牙开关状态</view>
			<button type="primary" @tap="openBluetoothAdapter('初始化蓝牙适配器')">初始化蓝牙适配器</button>
			<button type="primary" :disabled="!open" @tap="closeBluetoothAdapter('关闭蓝牙模块')">关闭蓝牙模块</button>
			<button type="primary" :disabled="!open" @tap="getBluetoothAdapterState('获取本机蓝牙适配器状态')">获取本机蓝牙适配器状态</button>
			<button type="primary" :disabled="!open" :loading="stateChange" @tap="onBluetoothAdapterStateChange('监听蓝牙适配器状态变化事件')">监听蓝牙适配器状态变化事件</button>

			<view class="title">扫描蓝牙设备</view>
			<button type="primary" :disabled="!available||discovering" :loading="discovering" @tap="startBluetoothDevicesDiscovery('开始搜寻附近的蓝牙外围设备')">开始搜寻附近的蓝牙外围设备</button>
			<button type="primary" :disabled="!discovering" @tap="stopBluetoothDevicesDiscovery('停止搜寻附近的蓝牙外围设备')">停止搜寻附近的蓝牙外围设备</button>
			<button type="primary" :disabled="!available||!mainServices.length" @tap="getConnectedBluetoothDevices('根据 uuid 获取处于已连接状态的设备')">根据
				uuid 获取处于已连接状态的设备</button>
			<button type="primary" :disabled="!available" @tap="getBluetoothDevices('获取所有已发现的蓝牙设备')">获取所有已发现的蓝牙设备</button>
			<button type="primary" :disabled="!available" :loading="deviceFound" @tap="onBluetoothDeviceFound('监听寻找到新设备的事件')">监听寻找到新设备的事件</button>

			<view class="title">连接设备</view>
			<button type="primary" :disabled="!deviceId" :loading="connecting" @tap="createBLEConnection('连接低功耗蓝牙设备')">连接低功耗蓝牙设备</button>
			<button type="primary" :disabled="!connected" @tap="closeBLEConnection('断开与低功耗蓝牙设备的连接')">断开与低功耗蓝牙设备的连接</button>
			<button type="primary" :disabled="!connected" @tap="getBLEDeviceServices('获取蓝牙设备所有服务')">获取蓝牙设备所有服务</button>
			<button type="primary" :disabled="!connected||!services.length" @tap="getBLEDeviceCharacteristics('获取蓝牙设备所有特征值')">获取蓝牙设备所有特征值</button>

			<view class="title">读写数据</view>
			<!-- <button type="primary" @tap="readBLECharacteristicValue">读取低功耗蓝牙设备的特征值的二进制数据值</button> -->
			<!-- ||!electricity -->
			<button type="primary" :disabled="!connected" @tap="readElectricity('读取电量')">读取电量</button>
			<button type="primary" :disabled="!connected||!steps" @tap="readSteps('读取步数')">读取步数</button>
			<button type="primary" :disabled="!connected||!currentTime" @tap="readCurrentTime('读取时间')">读取时间</button>
			<!-- <button type="primary" @tap="writeBLECharacteristicValue">向低功耗蓝牙设备特征值中写入二进制数据</button> -->
			<button type="primary" :disabled="!connected" @tap="writeShock('发送振动指令')">发送振动指令</button>
			<!-- ||!shock" -->
			<!-- <button type="primary" @tap="notifyBLECharacteristicValueChange">启用低功耗蓝牙设备特征值变化时的 notify 功能</button> -->

			<view class="title">其他事件</view>
			<button type="primary" :disabled="!connected||!steps" :loading="stepsNotify" @tap="notifySteps('监听步数')">监听步数</button>
			<button type="primary" :disabled="!available" :loading="connectionStateChange" @tap="onBLEConnectionStateChange('监听低功耗蓝牙连接的错误事件')">监听低功耗蓝牙连接的错误事件</button>
			<button type="primary" :disabled="!available" :loading="valueChange" @tap="onBLECharacteristicValueChange('监听低功耗蓝牙设备的特征值变化')">监听低功耗蓝牙设备的特征值变化</button>
		</view>
	</view>
</template>


<script>
	var deviceId = ''
	var mainServices = []
	var NAME = 'MI'
	// var NAME = 'MI Band 2'

	// 心率控制 2a39
	// var HEART_RATE_CONTROL_POINT
	// 心率通知 2a37
	// var HEART_RATE_MEASUREMENT
	// 警报控制 2a44
	// var ALERT_NOTIFICATION_CONTROL_POINT
	// 新警报 2a46
	// var NEW_ALERT
	// 当前时间 2a2b
	var CURRENT_TIME = '00002a2b'
	var currentTime = {}
	// 剩余电量ID
	var ELECTRICITY = '0000ff0c'
	var electricity = {
		serviceId: '',
		characteristicId: ''
	}
	// 震动ID
	var SHOCK = '00002a06'
	var shock = {
		serviceId: '',
		characteristicId: ''
	}
	// 步数
	var STEPS = '0000ff06'
	var steps = {
		serviceId: '',
		characteristicId: ''
	}
	var services = []
	export default {
		data() {
			return {
				// 开启状态
				open: false,
				// 可用状态
				available: false,
				// 搜索状态
				discovering: false,
				// 状态变化监听
				stateChange: false,
				// 新设备监听
				deviceFound: false,
				// 正在连接
				connecting: false,
				// 设备ID
				deviceId: '',
				// 连接状态
				connected: false,
				// 服务列表
				services: [],
				// 主服务列表
				mainServices: [],
				// 电量信息
				electricity: false,
				// 振动信息
				shock: false,
				// 步数信息
				steps: false,
				// 时间信息
				currentTime: false,
				// 步数监听
				stepsNotify: false,
				// 连接错误状态监听
				connectionStateChange: false,
				// 特征值变化监听
				valueChange: false
			}
		},
		methods: {
			setData(data) {
				for (let key in data) {
					this[key] = data[key]
				}
			},
			// 弹窗显示结果
			showAlert(title, content) {
				uni.showToast({
					title: title,
					content: content,
					butonText: '确定'
				})
			},
			// 初始化蓝牙适配器
			openBluetoothAdapter(title) {
				var self = this
				uni.openBluetoothAdapter({
					success(res) {
						console.log('openBluetoothAdapter success', res)
						self.showAlert(title, res)
						self.setData({
							open: true
						})
					},
					fail(e) {
						console.log('openBluetoothAdapter fail', e)
					}
				})
			},
			// 关闭蓝牙模块。
			closeBluetoothAdapter(title) {
				var self = this
				uni.closeBluetoothAdapter({
					success(res) {
						console.log('closeBluetoothAdapter success', res)
						self.showAlert(title, res)
						self.setData({
							open: false,
							available: false,
							discovering: false,
							connecting: false,
							deviceId: '',
							connected: false,
							services: [],
							mainServices: [],
							electricity: false,
							shock: false,
							steps: false,
							currentTime: false,
							stepsNotify: false
						})
					},
					fail(e) {
						console.log('closeBluetoothAdapter fail', e)
					}
				})
			},
			// 获取本机蓝牙适配器状态
			getBluetoothAdapterState(title) {
				var self = this
				uni.getBluetoothAdapterState({
					success(res) {
						console.log('getBluetoothAdapterState success', res)
						self.showAlert(title, res)
						self.setData({
							available: res.available,
							discovering: res.discovering
						})
					},
					fail(e) {
						console.log('getBluetoothAdapterState fail', e)
					}
				})
			},
			// 监听蓝牙适配器状态变化事件
			onBluetoothAdapterStateChange(title) {
				var self = this
				uni.onBluetoothAdapterStateChange(function(res) {
					console.log('onBluetoothAdapterStateChange res', res)
					self.showAlert(title, res)
					self.setData({
						available: res.available,
						discovering: res.discovering
					})
				})
				this.setData({
					stateChange: true
				})
			},
			// 开始搜寻附近的蓝牙外围设备
			startBluetoothDevicesDiscovery(title) {
				var self = this
				uni.startBluetoothDevicesDiscovery({
					success(res) {
						console.log('startBluetoothDevicesDiscovery success', res)
						self.showAlert(title, res)
						self.setData({
							discovering: true
						})
					},
					fail(e) {
						console.log('startBluetoothDevicesDiscovery fail', e)
					}
				})
			},
			// 停止搜寻附近的蓝牙外围设备
			stopBluetoothDevicesDiscovery(title) {
				var self = this
				uni.stopBluetoothDevicesDiscovery({
					success(res) {
						console.log('stopBluetoothDevicesDiscovery success', res)
						self.showAlert(title, res)
						self.setData({
							discovering: false
						})
					},
					fail(e) {
						console.log('stopBluetoothDevicesDiscovery fail', e)
					}
				})
			},
			// 根据 uuid 获取处于已连接状态的设备
			getConnectedBluetoothDevices(title) {
				var self = this
				uni.getConnectedBluetoothDevices({
					services: mainServices,
					success(res) {
						console.log('getConnectedBluetoothDevices success', res)
						self.showAlert(title, res)
						var devices = res.devices
						if (devices && devices.length) {
							deviceId = devices[0].deviceId
							self.setData({
								deviceId
							})
						}
					},
					fail(e) {
						console.log('getConnectedBluetoothDevices fail', e)
					}
				})
			},
			// 获取所有已发现的蓝牙设备
			getBluetoothDevices(title) {
				var self = this
				uni.getBluetoothDevices({
					success(res) {
						console.log('getBluetoothDevices success', res)
						self.showAlert(title, res)
						var devices = res.devices

						function pick() {
							var items = []
							var end = 0
							for (var i = 0; i < 6 && i + start < itemList.length; i++) {
								items.push(itemList[i + start])
								end = i + start
							}

							function fail() {
								if (end < itemList.length) {
									start += 6
									pick()
								}
							}
							if (items.length) {
								uni.showActionSheet({
									itemList: items,
									success: function(res) {
										var index = res.tapIndex
										// 此处微信web开发工具有bug，取消会触发成功的回调
										if (typeof index !== 'number') {
											return
										}
										deviceId = devices[index + start].deviceId
										self.setData({
											deviceId
										})
									},
									fail: function(res) {
										console.log(res.errMsg)
										self.showAlert(title, res)
										fail()
									}
								})
							}
						}
						if (devices.length) {
							var itemList = []
							var start = 0

							devices.forEach(device => {
								var name = device.name || device.deviceId
								// if('Gprinter_FEE3'==name){
									itemList.push(name)
									console.log('蓝牙设备device.name', name)
									console.log('device.deviceId==',device.deviceId)
									self.showAlert(title, name)
									if (!uni.showActionSheet) {
										if (device.name === NAME || device.localName === NAME) {
											deviceId = device.deviceId
											self.setData({
												deviceId
											})
										}
									}
								// }
								
							})
							if (uni.showActionSheet) {
								pick()
							}
						}
					},
					fail(e) {
						console.log('getBluetoothDevices fail', e)
					}
				})
			},
			// 监听寻找到新设备的事件
			onBluetoothDeviceFound(title) {
				var self = this
				uni.onBluetoothDeviceFound(res => {
					console.log('onBluetoothDeviceFound res', res)
					self.showAlert(title, res)
					var devices = res.devices
					devices.forEach(device => {
						// 此处开发者工具和真机表现不一致，需判断
						if (Array.isArray(device)) {
							device = device[0]
						}
						var name = device.name || device.deviceId
						console.log('device.name', name)
						if (uni.showToast) {
							uni.showToast({
								title: name
							})
						} else if (name === NAME || device.localName === NAME) {
							deviceId = device.deviceId
							self.setData({
								deviceId
							})
						}
					})
				})
				this.setData({
					deviceFound: true
				})
			},
			// 连接低功耗蓝牙设备
			createBLEConnection(title) {
				console.log("deviceId==="+deviceId);
				var self = this
				uni.createBLEConnection({
					deviceId,
					success(res) {
						console.log('createBLEConnection success', res)
						self.showAlert(title, res)
						self.setData({
							connected: true,
							connecting: false
						})
					},
					fail(e) {
						console.log('createBLEConnection fail', e)
						self.setData({
							connecting: false
						})
					}
				})
				this.setData({
					connecting: true
				})
			},
			// 断开与低功耗蓝牙设备的连接
			closeBLEConnection(title) {
				var self = this
				uni.closeBLEConnection({
					deviceId,
					success(res) {
						console.log('closeBLEConnection success', res)
						self.showAlert(title, res)
						self.setData({
							connected: false,
							stepsNotify: false
						})
					},
					fail(e) {
						console.log('closeBLEConnection fail', e)
					}
				})
			},
			// 获取蓝牙设备所有 service
			getBLEDeviceServices(title) {
				var self = this
				uni.getBLEDeviceServices({
					deviceId,
					success(res) {
						uni.showToast({
							title:'hh'+deviceId
						})
						console.log('getBLEDeviceServices success', res)
						self.showAlert(title, res)
						services = res.services
						services.forEach(service => {
							// if (service.isPrimary) {
								mainServices.push(service.uuid)
							// }
						})
						uni.setStorageSync('mainServices', mainServices)
						self.setData({
							services,
							mainServices
						})
					},
					fail(e) {
						uni.showToast({
							title:''+e.errCode
						})
						console.log('getBLEDeviceServices fail', e)
					}
				})
			},
			onLoad() {
				mainServices = uni.getStorageSync('mainServices') || []
				this.setData({
					mainServices: mainServices
				})
			},
			// 获取蓝牙设备所有 characteristic（特征值）
			getBLEDeviceCharacteristics(title) {
				var self = this
				services.forEach(service => {
					console.log('service.uuid', service.uuid);
					console.log('deviceId', deviceId)
					uni.getBLEDeviceCharacteristics({
						deviceId,
						serviceId: service.uuid,
						success(res) {
							console.log('getBLEDeviceCharacteristics success', res)
							self.showAlert(title, res)
							var characteristics = res.characteristics
							characteristics.forEach(characteristic => {
								var uuid = characteristic.uuid
								var type = 'other'

								function setType(type_, type__) {
									type_.characteristicId = uuid
									type_.serviceId = service.uuid
									type = type__
									var data = {}
									data[type__] = true
									self.setData(data)
								}
								switch (uuid.toLowerCase().substr(0, 8)) {
									case ELECTRICITY:
										{
											setType(electricity, 'electricity')
											break
										}
									case SHOCK:
										{
											setType(shock, 'shock')
											break
										}
									case STEPS:
										{
											setType(steps, 'steps')
											break
										}
									case CURRENT_TIME:
										{
											setType(currentTime, 'currentTime')
											break
										}
								}

								console.log(type + ' ' + 'characteristicId:', uuid)
							})
						},
						fail(e) {
							self.showAlert(title, e)
							console.log('getBLEDeviceCharacteristics fail', e)
						}
					})
				})
			},
			// 读取低功耗蓝牙设备的特征值的二进制数据值。
			readBLECharacteristicValue(title, type) {
				var self = this
				uni.readBLECharacteristicValue({
					deviceId,
					serviceId: type.serviceId,
					characteristicId: type.characteristicId,
					success(res) {
						console.log('readBLECharacteristicValue success', res)
						self.showAlert(title, res)
					},
					fail(e) {
						console.log('readBLECharacteristicValue fail', e)
					}
				})
			},
			// 读取电量
			readElectricity(title) {
				this.readBLECharacteristicValue(title, electricity)
			},
			// 读取步数
			readSteps(title) {
				this.readBLECharacteristicValue(title, steps)
			},
			// 读取时间
			readCurrentTime(title) {
				this.readBLECharacteristicValue(title, currentTime)
			},
			// 向低功耗蓝牙设备特征值中写入二进制数据。
			writeBLECharacteristicValue(title, type, value) {
				var self = this
				uni.writeBLECharacteristicValue({
					deviceId,
					serviceId: type.serviceId,
					characteristicId: type.characteristicId,
// 					serviceId: '00001801-0000-1000-8000-00805F9B34FB',
// 					characteristicId: '00002A05-0000-1000-8000-00805F9B34FB',
					value,
					success(res) {
						console.log('writeBLECharacteristicValue success', res)
						self.showAlert(title, res)
					},
					fail(e) {
						console.log('writeBLECharacteristicValue fail', e)
					}
				})
			},
			// 发送振动指令
			writeShock(title) {
				var buffer = new ArrayBuffer(16)
// 				var dataView = new DataView(buffer)
// 				dataView.setUint8(0, 1)
				
				var int32View = new Int32Array(buffer);

				for (var i=0; i<int32View.length; i++) {
				  int32View[i] = i*2;
				}
				this.writeBLECharacteristicValue(title, shock, buffer)
			},
			// 启用低功耗蓝牙设备特征值变化时的 notify 功能
			notifyBLECharacteristicValueChange(title, type, state, success, fail) {
				var self = this
				uni.notifyBLECharacteristicValueChange({
					deviceId,
					serviceId: type.serviceId,
					characteristicId: type.characteristicId,
					state: typeof state === 'boolean' ? state : true,
					success(res) {
						console.log('notifyBLECharacteristicValueChange success', res)
						self.showAlert(title, res)
						if (typeof success === 'function') {
							success(res)
						}
					},
					fail(e) {
						console.log('notifyBLECharacteristicValueChange fail', e)
						if (typeof fail === 'function') {
							fail(e)
						}
					}
				})
			},
			// 监听步数
			notifySteps(title) {
				this.notifyBLECharacteristicValueChange(title, steps, true, res => {
					this.setData({
						stepsNotify: true
					})
				})
			},
			// 监听低功耗蓝牙连接的错误事件
			onBLEConnectionStateChange(title) {
				var self = this
				uni.onBLEConnectionStateChange(res => {
					console.log('onBLEConnectionStateChange res', res)
					self.showAlert(title, res)
					if (!res.connected) {
						self.setData({
							connected: false,
							stepsNotify: false
						})
					}
				})
				this.setData({
					connectionStateChange: true
				})
			},
			// 监听低功耗蓝牙设备的特征值变化
			onBLECharacteristicValueChange(title) {
				uni.onBLECharacteristicValueChange(res => {
					console.log('onBLECharacteristicValueChange res', res)
					this.showAlert(title, res)
					if (res.value) {
						var dataView = new DataView(res.value)
						var value = []
						for (var i = 0; i < dataView.byteLength; i++) {
							value.push(dataView.getUint8(i))
						}
						if (res.characteristicId.toLowerCase().substr(0, 8) === CURRENT_TIME) {
							value = `${value[2]}-${value[3]} ${value[4]}:${value[5]}:${value[6]}`
						} else {
							value = value.splice(',')
						}
						console.log(value)
						if (uni.showToast) {
							uni.showToast({
								title: String(value)
							})
						}
					}
				})
				this.setData({
					valueChange: true
				})
			}
		},
		mounted() {
			this.onLoad()
		}
	}
</script>

<style>
	.win {
		padding: 15px;
	}

	.btn-area {
		padding: 0px 15px;
		/* background-color: #FFFFFF; */
		box-shadow: 0 0 10px 1px #EBEBEB;
		border-radius: 5px;
		overflow: hidden;
	}

	.btn-area .title {
		padding: 5px 0px;
		line-height: 40px;
	}
</style>
